package com.xiaoxin.common.shiro;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xiaoxin.common.entity.ShiroUser;
import com.xiaoxin.common.exception.PasswordErrorException;
import com.xiaoxin.entity.SysUser;
import com.xiaoxin.service.ISysUserService;
import com.xiaoxin.service.ITUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

import java.lang.reflect.InvocationTargetException;
import java.util.Objects;

/**
 * @version v1.0
 * @Description: 自定义Realm Shiro 的认证授权逻辑
 * @Author: TongRui乀
 * @Date: 2021/11/23 3:33 下午
 */
@Slf4j
public class CustomRealm extends AuthorizingRealm {
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        log.info("Shiro 授权");
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        log.info("Shiro 认证");
        String userName = (String) authenticationToken.getPrincipal();
        String password = new String((char[]) authenticationToken.getCredentials());
        ISysUserService userService = SpringUtil.getBean(ISysUserService.class);
        SysUser user = userService.getOne(new QueryWrapper<SysUser>().eq("user_name", userName));
        if(Objects.isNull(user)){
            throw new UnknownAccountException();
        }
        // 计算加盐密码
        String saltPassword = SecureUtil.md5(password + user.getSalt());
        if(!saltPassword.equals(user.getPassword())){
            // 登录失败
            throw new PasswordErrorException();
        }
        ShiroUser shiroUser = getShiroUser(user);
        // 登录成功
        return new SimpleAuthenticationInfo(shiroUser, password, ByteSource.Util.bytes(user.getSalt()), "customRealm");
    }

    private ShiroUser getShiroUser(SysUser user){

        ShiroUser shiroUser = new ShiroUser();

        BeanUtil.copyProperties(user, shiroUser, true);

        return shiroUser;
    }
}
